/**************************************************************************//**
 * @file     hal_stm32f1xx_rcc_api.h
 * @brief    stm32f1xx rcc 模块对外提供的公共接口
 * @version  V0.0.1
 * @date     2020-02-01
 ******************************************************************************/
/*
 * Copyright (c) 2020, 2020 by xiao xiang. All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * is freely granted, provided that this notice is preserved.
 */

#ifndef _HAL_STM32F1XX_RCC_API_H_
#define _HAL_STM32F1XX_RCC_API_H_

#include "common.h"
#include "hal_stm32f1xx_reg_base_api.h"

#define HAL_HSI_FREQ         (8 * 1000 * 1000)

#define HAL_SYSCLK_FREQ_8M   (8 * 1000 * 1000)       // stm32f1xx启动采用HSI默认频率
#define HAL_SYSCLK_FREQ_72M  (72 * 1000 * 1000)      // stm32f1xx支持的最高频率

#define HAL_HCLK_FREQ_8M    HAL_SYSCLK_FREQ_8M      // SYSCLK和HCLK默认保持一致
#define HAL_HCLK_FREQ_72M   HAL_SYSCLK_FREQ_72M     // SYSCLK和HCLK默认保持一致

/**************************************************************************//**
 * @file     hal_stm32f1xx_rcc_api.h
 * @brief    stm32f1xx RCC模块对外提供的公共接口
 * @version  V0.0.1
 * @date     2020-02-01
 ******************************************************************************/
/** 
  * @brief Bit definition for RCC_CR register 时钟控制寄存器
  * @note 复位值: 0x000 XX83， X代表未定义
  */
typedef union {
    struct {
        __IOM uint32_t HSION  : 1; /*!< 内部高速时钟使能 0=内部8MHz振荡器关闭 1=内部8MHz振荡器开启 */
        __IM  uint32_t HSIRDY : 1; /*!< 内部高速时钟就绪标志 0=时钟就绪 1=时钟没有就绪 */
             uint32_t RSV1   : 1;
        __IOM uint32_t HSITRIM: 5; /*!< 内部高速时钟调整，根据电压和温度变化调整 */
        __IM  uint32_t HSICAL : 8; /*!< 内部高速时钟校准 */
        __IOM uint32_t HSEON  : 1; /*!< 外部高速时钟使能 0=HSE关闭 1=HSE开启 */
        __IM  uint32_t HSERDY : 1; /*!< 外部高速时钟就绪标志 0=外部HSE没有就绪 1=HSE就绪*/
        __IOM uint32_t HSEBYP : 1; /*!< 外部高速时钟旁路，旁路意思是时钟直接输入，不用晶振 */
        __IOM uint32_t CSSON  : 1; /*!< 时钟安全系统使能 0=侦测关闭 1=侦测开启*/
             uint32_t RSV2   : 4;
        __IOM uint32_t PLLON  : 1; /*!< 0=PLL关闭 1=PLL使能 由软件置1或清零，进入待机和停止模式时，由硬件清零 */
        __IM  uint32_t PLLRDY : 1; /*!< PLL时钟就绪标志 (由硬件置1) 0=PLL未锁定 1=PLL锁定 */
             uint32_t RSV3   : 6;
    };
    uint32_t reg;
}UN_RCC_CR;

#define RCC_CR_HSION_ENABLE     1
#define RCC_CR_HSION_DISABLE    0

/** 
  * @brief Bit definition for RCC_CFGR register 时钟配置寄存器
  * @note 复位值: 0x0000 0000
  */
typedef union {
    struct {
        __IOM uint32_t SW       : 2; /*!< 系统时钟来源选择，可以是HSI/HSE/PLL */
        __IM  uint32_t SWS      : 2; /*!< 系统时钟切换状态，判断当前时钟源是HSI/HSE/PLL */
        __IOM uint32_t HPRE     : 4; /*!< AHB分频SYSCLK系数 */
        __IOM uint32_t PPRE1    : 3; /*!< 低速APB1分频HCLK系数 */
        __IOM uint32_t PPRE2    : 3; /*!< 高速APB2分频HCLK系数 */
        __IOM uint32_t ADCPRE   : 2; /*!< ADC分频PCLK2系数 */
        __IOM uint32_t PLLSRC   : 1; /*!< PLL输入时钟源 可以是HSI二分频或HSE */
        __IOM uint32_t PLLXTPRE : 1; /*!< HSE分频器作为PLL输入时是否分频 0=不分频 1=2分频 */
        __IOM uint32_t PLLMUL   : 4; /*!< PLL倍频系数 */
        __IOM uint32_t USBPRE   : 1; /*!< USB预分配 */
             uint32_t RSV1     : 1;
        __IOM uint32_t MC0      : 3; /*!< 时钟输出配置 */
             uint32_t RSV2     : 5;
    };
    uint32_t reg;
}UN_RCC_CFGR;

#define RCC_CFGR_SW_OFFSET  0
#define RCC_CFGR_SW_HSI     0x0    /*!< HSI作为系统时钟 */
#define RCC_CFGR_SW_HSE     0x1    /*!< HSE作为系统时钟 */
#define RCC_CFGR_SW_PLL     0x2    /*!< PLL作为系统时钟 */

#define RCC_CFGR_SWS_OFFSET 2
#define RCC_CFGR_SWS_HSI    0x0   /*!< 系统时钟状态，当前HSI作为系统时钟 */
#define RCC_CFGR_SWS_HSE    0x1   /*!< 系统时钟状态，当前HSE作为系统时钟 */
#define RCC_CFGR_SWS_PLL    0x2   /*!< 系统时钟状态，当前PLL作为系统时钟 */

#define RCC_CFGR_HPRE_OFFSET    4
#define RCC_CFGR_HPRE_DIV1      0x0  /*!< SYSCLK not divided */
#define RCC_CFGR_HPRE_DIV2      0x8  /*!< SYSCLK divided by 2 */
#define RCC_CFGR_HPRE_DIV4      0x9  /*!< SYSCLK divided by 4 */
#define RCC_CFGR_HPRE_DIV8      0xA  /*!< SYSCLK divided by 8 */
#define RCC_CFGR_HPRE_DIV16     0xB  /*!< SYSCLK divided by 16 */
#define RCC_CFGR_HPRE_DIV64     0xC  /*!< SYSCLK divided by 64 */
#define RCC_CFGR_HPRE_DIV128    0xD  /*!< SYSCLK divided by 128 */
#define RCC_CFGR_HPRE_DIV256    0xE  /*!< SYSCLK divided by 256 */
#define RCC_CFGR_HPRE_DIV512    0xF  /*!< SYSCLK divided by 512 */

#define RCC_CFGR_PPRE1_OFFSET   8
#define RCC_CFGR_PPRE1_DIV1     0x0  /*!< HCLK not divided */
#define RCC_CFGR_PPRE1_DIV2     0x4  /*!< HCLK divided by 2 */
#define RCC_CFGR_PPRE1_DIV4     0x5  /*!< HCLK divided by 4 */
#define RCC_CFGR_PPRE1_DIV8     0x6  /*!< HCLK divided by 8 */
#define RCC_CFGR_PPRE1_DIV16    0x7  /*!< HCLK divided by 16 */

#define RCC_CFGR_PPRE2_OFFSET   11
#define RCC_CFGR_PPRE2_DIV1     0x0  /*!< HCLK not divided */
#define RCC_CFGR_PPRE2_DIV2     0x4  /*!< HCLK divided by 2 */
#define RCC_CFGR_PPRE2_DIV4     0x5  /*!< HCLK divided by 4 */
#define RCC_CFGR_PPRE2_DIV8     0x6  /*!< HCLK divided by 8 */
#define RCC_CFGR_PPRE2_DIV16    0x7  /*!< HCLK divided by 16 */

#define RCC_CFGR_ADCPRE_OFFSET  14
#define RCC_CFGR_ADCPRE_DIV2    0x0  /*!< PCLK2 divided by 2 */
#define RCC_CFGR_ADCPRE_DIV4    0x1  /*!< PCLK2 divided by 4 */
#define RCC_CFGR_ADCPRE_DIV6    0x2  /*!< PCLK2 divided by 6 */
#define RCC_CFGR_ADCPRE_DIV8    0x3  /*!< PCLK2 divided by 8 */

#define RCC_CFGR_PLLSRC_OFFSET  16
#define RCC_CFGR_PLLSRC_HSI     0x0  /*!< HSI振荡器时钟经2分频后作为PLL输入时钟 */
#define RCC_CFGR_PLLSRC_HSE     0x1  /*!< HSE时钟作为PLL输入时钟 */

#define RCC_CFGR_PLLXTPRE_OFFSET 17
#define RCC_CFGR_PLLXTPRE_HSE1  0x0  /*!< HSE不分频 */
#define RCC_CFGR_PLLXTPRE_HSE2  0x1  /*!< HSE 2分频 */

#define RCC_CFGR_PLLMUL_OFFSET  18
#define RCC_CFGR_PLLMUL_DIV2    0x0  /*!< PLL 2倍频输出 */
#define RCC_CFGR_PLLMUL_DIV3    0x1  /*!< PLL 3倍频输出 */
#define RCC_CFGR_PLLMUL_DIV4    0x2  /*!< PLL 4倍频输出 */
#define RCC_CFGR_PLLMUL_DIV5    0x3  /*!< PLL 5倍频输出 */
#define RCC_CFGR_PLLMUL_DIV6    0x4  /*!< PLL 6倍频输出 */
#define RCC_CFGR_PLLMUL_DIV7    0x5  /*!< PLL 7倍频输出 */
#define RCC_CFGR_PLLMUL_DIV8    0x6  /*!< PLL 8倍频输出 */
#define RCC_CFGR_PLLMUL_DIV9    0x7  /*!< PLL 9倍频输出 */
#define RCC_CFGR_PLLMUL_DIV10   0x8  /*!< PLL 10倍频输出 */
#define RCC_CFGR_PLLMUL_DIV11   0x9  /*!< PLL 11倍频输出 */
#define RCC_CFGR_PLLMUL_DIV12   0xA  /*!< PLL 12倍频输出 */
#define RCC_CFGR_PLLMUL_DIV13   0xB  /*!< PLL 13倍频输出 */
#define RCC_CFGR_PLLMUL_DIV14   0xC  /*!< PLL 14倍频输出 */
#define RCC_CFGR_PLLMUL_DIV15   0xD  /*!< PLL 15倍频输出 */
#define RCC_CFGR_PLLMUL_DIV16   0xE  /*!< PLL 16倍频输出 */

#define RCC_CFGR_USBPRE_OFFSET  22
#define RCC_CFGR_USBPRE_PLL1    0x0  /*!< PLL时钟1.5倍分频作为USB时钟 */
#define RCC_CFGR_USBPRE_PLL15   0x1  /*!< PLL时钟直接作为USB时钟 */

#define RCC_CFGR_MCO_OFFSET         24
#define RCC_CFGR_MCO_NOCLOCK        0x0 /*!< 没有时钟输出 */
#define RCC_CFGR_MCO_SYSCLK         0x4 /*!< 系统时钟(SYSCLK)输出 */
#define RCC_CFGR_MCO_HSI            0x5 /*!< 内部RC振荡器时钟(HSI)输出 */
#define RCC_CFGR_MCO_HSE            0x6 /*!< 外部振荡器时钟(HSE)输出 */
#define RCC_CFGR_MCO_PLLCLK_DIV2    0x7 /*!< PLL时钟2分频后输出 */

/** 
  * @brief Bit definition for RCC_CIR register 时钟中断寄存器
  * @note 复位值: 0x0000 0000
  */
typedef union {
    struct {
        __IM  uint32_t LSIRDYF  : 1;  /*!< LSI就绪中断标志 (LSI ready interrupt flag)，只读，通过写*RDYC寄存器清除 */
        __IM  uint32_t LSERDYF  : 1;  /*!< LSE就绪中断标志 (LSE ready interrupt flag)，只读，通过写*RDYC寄存器清除 */
        __IM  uint32_t HSIRDYF  : 1;  /*!< HSI就绪中断标志 (HSI ready interrupt flag)，只读，通过写*RDYC寄存器清除 */
        __IM  uint32_t HSERDYF  : 1;  /*!< HSE就绪中断标志 (HSE ready interrupt flag)，只读，通过写*RDYC寄存器清除 */
        __IM  uint32_t PLLRDYF  : 1;  /*!< PLL就绪中断标志 (PLL ready interrupt flag)，只读，通过写*RDYC寄存器清除 */
              uint32_t RSV1     : 2;
        __IM  uint32_t CSSF     : 1;  /*!< 时钟安全系统中断标志 (Clock security system interrupt flag),硬件置1，写CSSC位1清除 */
        __IOM uint32_t LSIRDYIE : 1;  /*!< LSI就绪中断使能 (LSI ready interrupt enable)，写0=关闭中断 1=使能中断 */
        __IOM uint32_t LSERDYIE : 1;  /*!< LSE就绪中断使能 (LSE ready interrupt enable)，写0=关闭中断 1=使能中断 */
        __IOM uint32_t HSIRDYIE : 1;  /*!< HSI就绪中断使能 (HSI ready interrupt enable)，写0=关闭中断 1=使能中断 */
        __IOM uint32_t HSERDYIE : 1;  /*!< HSE就绪中断使能 (HSE ready interrupt enable)，写0=关闭中断 1=使能中断 */
        __IOM uint32_t PLLRDYIE : 1;  /*!< PLL就绪中断使能 (PLL ready interrupt enable)，写0=关闭中断 1=使能中断 */
              uint32_t RSV2     : 3;
        __IOM uint32_t LSIRDYC  : 1;  /*!< 清除LSI就绪中断 (LSI ready interrupt clear)，置1清除 */
        __IOM uint32_t LSERDYC  : 1;  /*!< 清除LSE就绪中断 (LSE ready interrupt clear)，置1清除 */
        __IOM uint32_t HISRDYC  : 1;  /*!< 清除HSI就绪中断 (HSI ready interrupt clear)，置1清除 */
        __IOM uint32_t HSERDYC  : 1;  /*!< 清除HSE就绪中断 (HSE ready interrupt clear)，置1清除 */
        __IOM uint32_t PLLRDYC  : 1;  /*!< 清除PLL就绪中断 (PLL ready interrupt clear)，置1清除 */
              uint32_t RSV3     : 2;
        __IOM uint32_t CSSC     : 1;  /*!< 清除时钟安全系统中断 (Clock security system interrupt clear)，置1清除 */
              uint32_t RSV4     : 8;
    };
    __IOM uint32_t reg;
} UN_RCC_CIR;

/** 
  * @brief Bit definition for RCC_APB2RSTR register APB2外设复位寄存器
  * @note 复位值: 0x0000 0000
  */
typedef union {
    struct {
        __IOM uint32_t AFIORST   : 1;   /*!< 辅助功能IO复位 (Alternate function I/O reset)，置1复位 */
              uint32_t RSV1      : 1;
        __IOM uint32_t IOPARST   : 1;   /*!< IO端口A复位 (IO port A reset)，置1复位 */
        __IOM uint32_t IOPBRST   : 1;   /*!< IO端口B复位 (IO port B reset)，置1复位 */
        __IOM uint32_t IOPCRST   : 1;   /*!< IO端口C复位 (IO port C reset)，置1复位 */
        __IOM uint32_t IOPDRST   : 1;   /*!< IO端口D复位 (IO port D reset)，置1复位 */
        __IOM uint32_t IOPERST   : 1;   /*!< IO端口E复位 (IO port E reset)，置1复位 */
        __IOM uint32_t IOPFRST   : 1;   /*!< IO端口F复位 (IO port F reset)，置1复位 */
        __IOM uint32_t IOPGRST   : 1;   /*!< IO端口G复位 (IO port G reset)，置1复位 */
        __IOM uint32_t ADC1RST   : 1;   /*!< ADC1接口复位 (ADC 1 interface reset)，置1复位 */
        __IOM uint32_t ADC2RST   : 1;   /*!< ADC2接口复位 (ADC 2 interface reset)，置1复位 */
        __IOM uint32_t TIM1RST   : 1;   /*!< TIM1定时器复位 (TIM1 timer reset)，置1复位 */
        __IOM uint32_t SPI1RST   : 1;   /*!< SPI1复位 (SPI 1 reset)，置1复位 */
        __IOM uint32_t TIM8RST   : 1;   /*!< TIM8定时器复位 (TIM8 timer reset)，置1复位 */
        __IOM uint32_t USART1RST : 1;   /*!< USART1复位 (USART1 reset)，置1复位 */
        __IOM uint32_t ADC3RST   : 1;   /*!< ADC3接口复位 (ADC3 interface reset)，置1复位 */
              uint32_t RSV2      : 16;
    };
    __IOM uint32_t reg;
}UN_RCC_APB2RSTR;

/** 
  * @brief Bit definition for RCC_APB1RSTR register APB1外设复位寄存器
  * @note 复位值： 0x0000 0000
  */
typedef union {
    struct {
        __IOM uint32_t TIM2RST   : 1;   /*!< 定时器2复位 (Timer 2 reset)，置1复位 */
        __IOM uint32_t TIM3RST   : 1;   /*!< 定时器3复位 (Timer 3 reset)，置1复位 */
        __IOM uint32_t TIM4RST   : 1;   /*!< 定时器4复位 (Timer 4 reset)，置1复位 */
        __IOM uint32_t TIM5RST   : 1;   /*!< 定时器5复位 (Timer 5 reset)，置1复位 */
        __IOM uint32_t TIM6RST   : 1;   /*!< 定时器6复位 (Timer 6 reset)，置1复位 */
        __IOM uint32_t TIM7RST   : 1;   /*!< 定时器7复位 (Timer 7 reset)，置1复位 */
        __IM  uint32_t  RSV1      : 5;
        __IOM uint32_t WWDGRST   : 1;   /*!< 窗口看门狗复位 (Window watchdog reset)，置1复位 */
        __IM  uint32_t  RSV2      : 2;
        __IOM uint32_t SPI2RST   : 1;   /*!< SPI2复位 (SPI 2 reset)，置1复位 */
        __IOM uint32_t SPI3RST   : 1;   /*!< SPI3 复位 (SPI 3 reset)，置1复位 */
        __IM  uint32_t  RSV3      : 1;
        __IOM uint32_t USART2RST : 1;   /*!< USART2复位 (USART 2 reset)，置1复位 */
        __IOM uint32_t USART3RST : 1;   /*!< USART3复位 (USART 3 reset)，置1复位 */
        __IOM uint32_t UART4RST  : 1;   /*!< UART4复位 (UART 4 reset)，置1复位 */
        __IOM uint32_t UART5RST  : 1;   /*!< UART5复位 (UART 5 reset)，置1复位 */
        __IOM uint32_t I2C1RST   : 1;   /*!< I2C 1复位 (I2C 1 reset)，置1复位 */
        __IOM uint32_t I2C2RST   : 1;   /*!< I2C 2复位 (I2C 2 reset)，置1复位 */
        __IOM uint32_t USBRST    : 1;   /*!< USB复位 (USB reset)，置1复位 */
        __IM  uint32_t  RSV4      : 1;
        __IOM uint32_t CANRST    : 1;   /*!< CAN复位 (CAN reset)，置1复位 */
        __IM  uint32_t  RSV5      : 1;
        __IOM uint32_t BKPRST    : 1;   /*!< 备份接口复位 (Backup interface reset)，置1复位 */
        __IOM uint32_t PWRRST    : 1;   /*!< 电源接口复位 (Power interface reset)，置1复位 */
        __IOM uint32_t DACRST    : 1;   /*!< DAC接口复位 (DAC interface reset)，置1复位 */
        __IM  uint32_t  RSV6      : 2;
    };
    __IOM uint32_t reg;
}UN_RCC_APB1RSTR;

/** 
  * @brief Bit definition for RCC_AHBENR register AHB外设时钟使能寄存器
  * @note 复位值： 0x0000 0014
  */
typedef union {
    struct {
        __IOM uint32_t DMA1EN  : 1;   /*!< DMA1时钟使能 (DMA1 clock enable),0=关闭时钟 1=开启时钟 */
        __IOM uint32_t DMA2EN  : 1;   /*!< DMA2时钟使能 (DMA2 clock enable),0=关闭时钟 1=开启时钟 */
        __IOM uint32_t SRAMEN  : 1;   /*!< SRAM时钟使能 (SRAM interface clock enable)，0=睡眠模式时关闭时钟 1=睡眠模式时开启时钟 */
              uint32_t RSV1    : 1;
        __IOM uint32_t FLITFEN : 1;   /*!< 闪存接口电路时钟使能 (FLITF clock enable)，0=睡眠模式时关闭时钟 1=睡眠模式时开启时钟 */
              uint32_t RSV2    : 1;
        __IOM uint32_t CRCEN   : 1;   /*!< CRC时钟使能 (CRC clock enable),0=关闭时钟 1=开启时钟 */
              uint32_t RSV3    : 1;
        __IOM uint32_t FSMCEN  : 1;   /*!< FSMC时钟使能 (FSMC clock enable),0=关闭时钟 1=开启时钟 */
              uint32_t RSV4    : 1;
        __IOM uint32_t SDIOEN  : 1;   /*!< SDIO时钟使能 (SDIO clock enable),0=关闭时钟 1=开启时钟 */
              uint32_t RSV5    : 21;
    };
    __IOM uint32_t reg;
}UN_RCC_AHBENR;

/** 
  * @brief Bit definition for RCC_APB2ENR register APB2外设时钟使能寄存器
  * @note 复位值： 0x0000 0000
  */
typedef union {
    struct {
        __IOM uint32_t AFIOEN   : 1;   /*!< 辅助功能IO时钟使能 (Alternate function I/O clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV1     : 1;
        __IOM uint32_t IOPAEN   : 1;   /*!< IO端口A时钟使能 (I/O port A clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t IOPBEN   : 1;   /*!< IO端口B时钟使能 (I/O port B clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t IOPCEN   : 1;   /*!< IO端口C时钟使能 (I/O port C clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t IOPDEN   : 1;   /*!< IO端口D时钟使能 (I/O port D clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t IOPEEN   : 1;   /*!< IO端口E时钟使能 (I/O port E clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t IOPFEN   : 1;   /*!< IO端口F时钟使能 (I/O port F clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t IOPGEN   : 1;   /*!< IO端口G时钟使能 (I/O port G clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t ADC1EN   : 1;   /*!< ADC1接口时钟使能 (ADC 1 interface clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t ADC2EN   : 1;   /*!< ADC2接口时钟使能 (ADC 2 interface clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t TIM1EN   : 1;   /*!< TIM1定时器时钟使能 (TIM1 Timer clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t SPI1EN   : 1;   /*!< SPI1时钟使能 (SPI 1 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t TIM8EN   : 1;   /*!< TIM8定时器时钟使能 (TIM8 Timer clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t USART1EN : 1;   /*!< USART1时钟使能 (USART1 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t ADC3EN   : 1;   /*!< ADC3接口时钟使能 (ADC 3 interface clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV2     : 16;
    };
    __IOM uint32_t reg;
}UN_RCC_APB2ENR;

/** 
  * @brief Bit definition for RCC_APB1ENR register APB1外设时钟使能寄存器
  * @note 复位值： 0x0000 0000
  */
typedef union {
    struct {
        __IOM uint32_t TIM2EN   : 1;   /*!< 定时器2时钟使能 (Timer 2 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t TIM3EN   : 1;   /*!< 定时器3时钟使能 (Timer 3 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t TIM4EN   : 1;   /*!< 定时器4时钟使能 (Timer 4 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t TIM5EN   : 1;   /*!< 定时器5时钟使能 (Timer 5 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t TIM6EN   : 1;   /*!< 定时器6时钟使能 (Timer 6 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t TIM7EN   : 1;   /*!< 定时器7时钟使能 (Timer 7 clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV1     : 5;
        __IOM uint32_t WWDGEN   : 1;   /*!< 窗口看门狗时钟使能 (Window watchdog clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV2     : 2;
        __IOM uint32_t SPI2EN   : 1;   /*!< SPI 2时钟使能 (SPI 2 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t SPI3EN   : 1;   /*!< SPI 3时钟使能 (SPI 3 clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV3     : 1;
        __IOM uint32_t USART2EN : 1;   /*!< USART2时钟使能 (USART 2 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t USART3EN : 1;   /*!< USART3时钟使能 (USART 3 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t UART4EN  : 1;   /*!< UART4时钟使能 (UART 4 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t UART5EN  : 1;   /*!< UART5时钟使能 (UART 5 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t I2C1EN   : 1;   /*!< I2C 1时钟使能 (I2C 1 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t I2C2EN   : 1;   /*!< I2C 2时钟使能 (I2C 2 clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t USBEN    : 1;   /*!< USB时钟使能 (USB clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV4     : 1;
        __IOM uint32_t CANEN    : 1;   /*!< CAN时钟使能 (CAN clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV5     : 1;
        __IOM uint32_t BKPEN    : 1;   /*!< 备份接口时钟使能 (Backup interface clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t PWREN    : 1;   /*!< 电源接口时钟使能 (Power interface clock enable) 0=关闭时钟 1=开启时钟 */
        __IOM uint32_t DACEN    : 1;   /*!< DAC接口时钟使能 (DAC interface clock enable) 0=关闭时钟 1=开启时钟 */
              uint32_t RSV6     : 2;
    };
    __IOM uint32_t reg;
}UN_RCC_APB1ENR;

/** 
  * @brief Bit definition for RCC_BDCR register 备份域控制寄存器
  * @note 复位值： 0x0000 0000，只能由备份域复位有效复位
  */
typedef union {
    struct {
        __IOM uint32_t LSEON  : 1;   /*!< 外部低速振荡器使能 (External low-speed oscillator enable) 0=外部晶振关闭 1=外部晶振开启 */
        __IM  uint32_t LSERDY : 1;   /*!< 外部低速LSE就绪 (External low-speed oscillator ready) 只读 0=外部晶振就绪 1=外部晶振未就绪 */
        __IOM uint32_t LSEBYP : 1;   /*!< 外部低速时钟振荡器旁路 (External low-speed oscillator bypass) 0=LSE时钟未旁路 1=LSE时钟旁路 */
              uint32_t RSV1   : 5;
        __IOM uint32_t RTCSEL : 2;   /*!< RTC时钟源选择 (RTC clock source selection) 00=无时钟 01=LSE 10=LSI 11=HSE 128分频 */
              uint32_t RSV2   : 5;
        __IOM uint32_t RTCEN  : 1;   /*!< RTC时钟使能 (RTC clock enable) 0=关闭 1=使能 */
        __IOM uint32_t BDRST  : 1;   /*!< 备份域软件复位 (Backup domain software reset) 0=复位未激活 1=复位整个备份域*/
              uint32_t RSV3   : 15;
    };
    __IOM uint32_t reg;
}UN_RCC_BDCR;

/** 
  * @brief Bit definition for RCC_CSR register 控制/状态寄存器
  * @note 复位值： 0x0C00 0000，除复位标志外由系统复位清除，复位标志只能由电源复位清除。
  */
typedef union {
    struct {
        __IOM uint32_t LSION    : 1;   /*!< 内部低速振荡器使能 (Internal low-speed oscillator enable) 0=LSI关闭 1=LSI开启 */
        __IM  uint32_t LSIRDY   : 1;   /*!< 内部低速振荡器就绪 (Internal low-speed oscillator ready) 0=LSI未就绪 1=LSI就绪 */
              uint32_t RSV1     : 22;
        __IOM uint32_t RMVF     : 1;   /*!< 清除复位标志 (Remove reset flag) 0=无作用 1=清除复位标志 */
              uint32_t RSV2     : 1;
        __IOM uint32_t PINRSTF  : 1;   /*!< NRST引脚复位标志 (PIN reset flag) 0=未发生NRST引脚复位 1=发生NRST引脚复位 */
        __IOM uint32_t PORRSTF  : 1;   /*!< 上电/掉电复位标志 (POR/PDR reset flag) 0=非硬启动 1=硬启动 */
        __IOM uint32_t SFTRSTF  : 1;   /*!< 软件复位标志 (Software reset flag) 0=非软件复位 1=软件复位 */
        __IOM uint32_t IWDGRSTF : 1;   /*!< 独立看门狗复位标志 (Independent watchdog reset flag) 0=非独立看门狗复位 1=独立看门狗复位*/
        __IOM uint32_t WWDGRSTF : 1;   /*!< 窗口看门狗复位标志 (Window watchdog reset flag) 0=非窗口看门狗复位 1=窗口看门狗复位 */
        __IOM uint32_t LPWRRSTF : 1;   /*!< 低功耗复位标志 (Low-power reset flag) 0=非低功耗管理复位 1=低功耗管理复位 */
    };
    __IOM uint32_t reg;
}UN_RCC_CSR;

/** 
  * @brief Reset and Clock Control
  */
typedef struct {
  __IOM UN_RCC_CR        CR;       /*!< 时钟控制寄存器 */
  __IOM UN_RCC_CFGR      CFGR;     /*!< 时钟配置寄存器 */
  __IOM UN_RCC_CIR       CIR;      /*!< 时钟中断寄存器 */
  __IOM UN_RCC_APB2RSTR  APB2RSTR; /*!< APB2外设复位寄存器 */
  __IOM UN_RCC_APB1RSTR  APB1RSTR; /*!< APB1外设复位寄存器 */
  __IOM UN_RCC_AHBENR    AHBENR;   /*!< AHB外设时钟使能寄存器 */
  __IOM UN_RCC_APB2ENR   APB2ENR;  /*!< APB2外设时钟使能寄存器 */
  __IOM UN_RCC_APB1ENR   APB1ENR;  /*!< APB1外设时钟使能寄存器 */
  __IOM UN_RCC_BDCR      BDCR;     /*!< 备份域控制寄存器 */
  __IOM UN_RCC_CSR       CSR;      /*!< 控制/状态寄存器 */
} RCC_TypeDef;

#define RCC     ((RCC_TypeDef *)RCC_BASE)

/**
  \brief   获取当前系统时钟频率
  \details 系统启动时，STM32F1XX系列默认是8M，使能外部8M晶振后最高可以达到72M
  \return  系统时钟频率
 */
uint32_t HAL_RccSysclkFreqGet(void);

/**
  \brief   使用外部晶振8M，并切换系统时钟频率为72M
  \details 重新配置系统时钟后，务必需要重新更新Systick
  \return  0：成功 1：失败
 */
uint32_t HAL_RccSwitchHse8mClk72m(void);

/**
  \brief   重新计算并获取当前SYSCLK的频率
  \return  SYSCLK频率值
 */
uint32_t HAL_RccGetSysclk(void);

/**
  \brief   重新计算并获取当前HCLK的频率
  \return  HCLK频率值
 */
uint32_t HAL_RccGetHclk(void);

/**
  \brief   重新计算并获取当前PCLK2的频率
  \return  PCLK2频率值
 */
uint32_t HAL_RccGetPclk2(void);

/**
  \brief   重新计算并获取当前PCLK1的频率
  \return  PCLK1频率值
 */
uint32_t HAL_RccGetPclk1(void);

#endif